001    /*
002     *  Copyright 2001-2007 Stephen Colebourne
003     *
004     *  Licensed under the Apache License, Version 2.0 (the "License");
005     *  you may not use this file except in compliance with the License.
006     *  You may obtain a copy of the License at
007     *
008     *      http://www.apache.org/licenses/LICENSE-2.0
009     *
010     *  Unless required by applicable law or agreed to in writing, software
011     *  distributed under the License is distributed on an "AS IS" BASIS,
012     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     *  See the License for the specific language governing permissions and
014     *  limitations under the License.
015     */
016    package org.joda.time;
017    
018    import java.io.IOException;
019    import java.io.ObjectInputStream;
020    import java.io.ObjectOutputStream;
021    import java.io.Serializable;
022    import java.util.Calendar;
023    import java.util.Date;
024    import java.util.HashSet;
025    import java.util.Locale;
026    import java.util.Set;
027    
028    import org.joda.time.base.BaseLocal;
029    import org.joda.time.chrono.ISOChronology;
030    import org.joda.time.convert.ConverterManager;
031    import org.joda.time.convert.PartialConverter;
032    import org.joda.time.field.AbstractReadableInstantFieldProperty;
033    import org.joda.time.format.DateTimeFormat;
034    import org.joda.time.format.ISODateTimeFormat;
035    
036    /**
037     * LocalTime is an immutable time class representing a time
038     * without a time zone.
039     * <p>
040     * LocalTime implements the {@link ReadablePartial} interface.
041     * To do this, the interface methods focus on the key fields -
042     * HourOfDay, MinuteOfHour, SecondOfMinute and MillisOfSecond.
043     * However, <b>all</b> time fields may in fact be queried.
044     * <p>
045     * Calculations on LocalTime are performed using a {@link Chronology}.
046     * This chronology will be set internally to be in the UTC time zone
047     * for all calculations.
048     *
049     * <p>Each individual field can be queried in two ways:
050     * <ul>
051     * <li><code>getHourOfDay()</code>
052     * <li><code>hourOfDay().get()</code>
053     * </ul>
054     * The second technique also provides access to other useful methods on the
055     * field:
056     * <ul>
057     * <li>numeric value
058     * <li>text value
059     * <li>short text value
060     * <li>maximum/minimum values
061     * <li>add/subtract
062     * <li>set
063     * <li>rounding
064     * </ul>
065     *
066     * <p>
067     * LocalTime is thread-safe and immutable, provided that the Chronology is as well.
068     * All standard Chronology classes supplied are thread-safe and immutable.
069     *
070     * @author Stephen Colebourne
071     * @since 1.3
072     */
073    public final class LocalTime
074            extends BaseLocal
075            implements ReadablePartial, Serializable {
076    
077        /** Serialization lock */
078        private static final long serialVersionUID = -12873158713873L;
079    
080        /** Constant for midnight. */
081        public static final LocalTime MIDNIGHT = new LocalTime(0, 0, 0, 0);
082    
083        /** The index of the hourOfDay field in the field array */
084        private static final int HOUR_OF_DAY = 0;
085        /** The index of the minuteOfHour field in the field array */
086        private static final int MINUTE_OF_HOUR = 1;
087        /** The index of the secondOfMinute field in the field array */
088        private static final int SECOND_OF_MINUTE = 2;
089        /** The index of the millisOfSecond field in the field array */
090        private static final int MILLIS_OF_SECOND = 3;
091        /** Set of known duration types. */
092        private static final Set TIME_DURATION_TYPES = new HashSet();
093        static {
094            TIME_DURATION_TYPES.add(DurationFieldType.millis());
095            TIME_DURATION_TYPES.add(DurationFieldType.seconds());
096            TIME_DURATION_TYPES.add(DurationFieldType.minutes());
097            TIME_DURATION_TYPES.add(DurationFieldType.hours());
098        }
099    
100        /** The local millis from 1970-01-01T00:00:00 */
101        private long iLocalMillis;
102        /** The chronology to use, in UTC */
103        private Chronology iChronology;
104    
105        //-----------------------------------------------------------------------
106        /**
107         * Constructs a LocalTime from the specified millis of day using the
108         * ISO chronology.
109         * <p>
110         * The millisOfDay value may exceed the number of millis in one day,
111         * but additional days will be ignored.
112         * This method uses the UTC time zone internally.
113         *
114         * @param millisOfDay  the number of milliseconds into a day to convert
115         */
116        public static LocalTime fromMillisOfDay(long millisOfDay) {
117            return fromMillisOfDay(millisOfDay, null);
118        }
119    
120        /**
121         * Constructs a LocalTime from the specified millis of day using the
122         * specified chronology.
123         * <p>
124         * The millisOfDay value may exceed the number of millis in one day,
125         * but additional days will be ignored.
126         * This method uses the UTC time zone internally.
127         *
128         * @param millisOfDay  the number of milliseconds into a day to convert
129         * @param chrono  the chronology, null means ISO chronology
130         */
131        public static LocalTime fromMillisOfDay(long millisOfDay, Chronology chrono) {
132            chrono = DateTimeUtils.getChronology(chrono).withUTC();
133            return new LocalTime(millisOfDay, chrono);
134        }
135    
136        //-----------------------------------------------------------------------
137        /**
138         * Constructs a LocalTime from a <code>java.util.Calendar</code>
139         * using exactly the same field values.
140         * <p>
141         * Each field is queried from the Calendar and assigned to the LocalTime.
142         * This is useful if you have been using the Calendar as a local time,
143         * ignoring the zone.
144         * <p>
145         * One advantage of this method is that this method is unaffected if the
146         * version of the time zone data differs between the JDK and Joda-Time.
147         * That is because the local field values are transferred, calculated using
148         * the JDK time zone data and without using the Joda-Time time zone data.
149         * <p>
150         * This factory method ignores the type of the calendar and always
151         * creates a LocalTime with ISO chronology. It is expected that you
152         * will only pass in instances of <code>GregorianCalendar</code> however
153         * this is not validated.
154         *
155         * @param calendar  the Calendar to extract fields from
156         * @return the created LocalTime
157         * @throws IllegalArgumentException if the calendar is null
158         * @throws IllegalArgumentException if the date is invalid for the ISO chronology
159         */
160        public static LocalTime fromCalendarFields(Calendar calendar) {
161            if (calendar == null) {
162                throw new IllegalArgumentException("The calendar must not be null");
163            }
164            return new LocalTime(
165                calendar.get(Calendar.HOUR_OF_DAY),
166                calendar.get(Calendar.MINUTE),
167                calendar.get(Calendar.SECOND),
168                calendar.get(Calendar.MILLISECOND)
169            );
170        }
171    
172        /**
173         * Constructs a LocalTime from a <code>java.util.Date</code>
174         * using exactly the same field values.
175         * <p>
176         * Each field is queried from the Date and assigned to the LocalTime.
177         * This is useful if you have been using the Date as a local time,
178         * ignoring the zone.
179         * <p>
180         * One advantage of this method is that this method is unaffected if the
181         * version of the time zone data differs between the JDK and Joda-Time.
182         * That is because the local field values are transferred, calculated using
183         * the JDK time zone data and without using the Joda-Time time zone data.
184         * <p>
185         * This factory method always creates a LocalTime with ISO chronology.
186         *
187         * @param date  the Date to extract fields from
188         * @return the created LocalTime
189         * @throws IllegalArgumentException if the calendar is null
190         * @throws IllegalArgumentException if the date is invalid for the ISO chronology
191         */
192        public static LocalTime fromDateFields(Date date) {
193            if (date == null) {
194                throw new IllegalArgumentException("The date must not be null");
195            }
196            return new LocalTime(
197                date.getHours(),
198                date.getMinutes(),
199                date.getSeconds(),
200                (((int) (date.getTime() % 1000)) + 1000) % 1000
201            );
202        }
203    
204        //-----------------------------------------------------------------------
205        /**
206         * Constructs an instance set to the current local time evaluated using
207         * ISO chronology in the default zone.
208         * <p>
209         * Once the constructor is completed, the zone is no longer used.
210         */
211        public LocalTime() {
212            this(DateTimeUtils.currentTimeMillis(), ISOChronology.getInstance());
213        }
214    
215        /**
216         * Constructs an instance set to the current local time evaluated using
217         * ISO chronology in the specified zone.
218         * <p>
219         * If the specified time zone is null, the default zone is used.
220         * Once the constructor is completed, the zone is no longer used.
221         *
222         * @param zone  the time zone, null means default zone
223         */
224        public LocalTime(DateTimeZone zone) {
225            this(DateTimeUtils.currentTimeMillis(), ISOChronology.getInstance(zone));
226        }
227    
228        /**
229         * Constructs an instance set to the current local time evaluated using
230         * specified chronology and zone.
231         * <p>
232         * If the chronology is null, ISO chronology in the default time zone is used.
233         * Once the constructor is completed, the zone is no longer used.
234         *
235         * @param chronology  the chronology, null means ISOChronology in default zone
236         */
237        public LocalTime(Chronology chronology) {
238            this(DateTimeUtils.currentTimeMillis(), chronology);
239        }
240    
241        //-----------------------------------------------------------------------
242        /**
243         * Constructs an instance set to the local time defined by the specified
244         * instant evaluated using ISO chronology in the default zone.
245         * <p>
246         * Once the constructor is completed, the zone is no longer used.
247         *
248         * @param instant  the milliseconds from 1970-01-01T00:00:00Z
249         */
250        public LocalTime(long instant) {
251            this(instant, ISOChronology.getInstance());
252        }
253    
254        /**
255         * Constructs an instance set to the local time defined by the specified
256         * instant evaluated using ISO chronology in the specified zone.
257         * <p>
258         * If the specified time zone is null, the default zone is used.
259         * Once the constructor is completed, the zone is no longer used.
260         *
261         * @param instant  the milliseconds from 1970-01-01T00:00:00Z
262         * @param zone  the time zone, null means default zone
263         */
264        public LocalTime(long instant, DateTimeZone zone) {
265            this(instant, ISOChronology.getInstance(zone));
266        }
267    
268        /**
269         * Constructs an instance set to the local time defined by the specified
270         * instant evaluated using the specified chronology.
271         * <p>
272         * If the chronology is null, ISO chronology in the default zone is used.
273         * Once the constructor is completed, the zone is no longer used.
274         *
275         * @param instant  the milliseconds from 1970-01-01T00:00:00Z
276         * @param chronology  the chronology, null means ISOChronology in default zone
277         */
278        public LocalTime(long instant, Chronology chronology) {
279            chronology = DateTimeUtils.getChronology(chronology);
280            
281            long localMillis = chronology.getZone().getMillisKeepLocal(DateTimeZone.UTC, instant);
282            chronology = chronology.withUTC();
283            iLocalMillis = chronology.millisOfDay().get(localMillis);
284            iChronology = chronology;
285        }
286    
287        //-----------------------------------------------------------------------
288        /**
289         * Constructs an instance from an Object that represents a datetime.
290         * <p>
291         * If the object contains no chronology, <code>ISOChronology</code> is used.
292         * If the object contains no time zone, the default zone is used.
293         * Once the constructor is completed, the zone is no longer used.
294         * <p>
295         * The recognised object types are defined in
296         * {@link org.joda.time.convert.ConverterManager ConverterManager} and
297         * include ReadablePartial, ReadableInstant, String, Calendar and Date.
298         * The String formats are described by {@link ISODateTimeFormat#localTimeParser()}.
299         * The default String converter ignores the zone and only parses the field values.
300         *
301         * @param instant  the datetime object
302         * @throws IllegalArgumentException if the instant is invalid
303         */
304        public LocalTime(Object instant) {
305            this(instant, (Chronology) null);
306        }
307    
308        /**
309         * Constructs an instance from an Object that represents a datetime,
310         * forcing the time zone to that specified.
311         * <p>
312         * If the object contains no chronology, <code>ISOChronology</code> is used.
313         * If the specified time zone is null, the default zone is used.
314         * Once the constructor is completed, the zone is no longer used.
315         * <p>
316         * The recognised object types are defined in
317         * {@link org.joda.time.convert.ConverterManager ConverterManager} and
318         * include ReadablePartial, ReadableInstant, String, Calendar and Date.
319         * The String formats are described by {@link ISODateTimeFormat#localTimeParser()}.
320         * The default String converter ignores the zone and only parses the field values.
321         *
322         * @param instant  the datetime object
323         * @param zone  the time zone
324         * @throws IllegalArgumentException if the instant is invalid
325         */
326        public LocalTime(Object instant, DateTimeZone zone) {
327            PartialConverter converter = ConverterManager.getInstance().getPartialConverter(instant);
328            Chronology chronology = converter.getChronology(instant, zone);
329            chronology = DateTimeUtils.getChronology(chronology);
330            iChronology = chronology.withUTC();
331            int[] values = converter.getPartialValues(this, instant, chronology, ISODateTimeFormat.localTimeParser());
332            iLocalMillis = iChronology.getDateTimeMillis(0L, values[0], values[1], values[2], values[3]);
333        }
334    
335        /**
336         * Constructs an instance from an Object that represents a datetime,
337         * using the specified chronology.
338         * <p>
339         * If the chronology is null, ISO in the default time zone is used.
340         * Once the constructor is completed, the zone is no longer used.
341         * <p>
342         * The recognised object types are defined in
343         * {@link org.joda.time.convert.ConverterManager ConverterManager} and
344         * include ReadablePartial, ReadableInstant, String, Calendar and Date.
345         * The String formats are described by {@link ISODateTimeFormat#localTimeParser()}.
346         * The default String converter ignores the zone and only parses the field values.
347         *
348         * @param instant  the datetime object
349         * @param chronology  the chronology
350         * @throws IllegalArgumentException if the instant is invalid
351         */
352        public LocalTime(Object instant, Chronology chronology) {
353            PartialConverter converter = ConverterManager.getInstance().getPartialConverter(instant);
354            chronology = converter.getChronology(instant, chronology);
355            chronology = DateTimeUtils.getChronology(chronology);
356            iChronology = chronology.withUTC();
357            int[] values = converter.getPartialValues(this, instant, chronology, ISODateTimeFormat.localTimeParser());
358            iLocalMillis = iChronology.getDateTimeMillis(0L, values[0], values[1], values[2], values[3]);
359        }
360    
361        //-----------------------------------------------------------------------
362        /**
363         * Constructs an instance set to the specified time
364         * using <code>ISOChronology</code>.
365         *
366         * @param hourOfDay  the hour of the day
367         * @param minuteOfHour  the minute of the hour
368         */
369        public LocalTime(
370                int hourOfDay,
371                int minuteOfHour) {
372            this(hourOfDay, minuteOfHour, 0, 0, ISOChronology.getInstanceUTC());
373        }
374    
375        /**
376         * Constructs an instance set to the specified time
377         * using <code>ISOChronology</code>.
378         *
379         * @param hourOfDay  the hour of the day
380         * @param minuteOfHour  the minute of the hour
381         * @param secondOfMinute  the second of the minute
382         */
383        public LocalTime(
384                int hourOfDay,
385                int minuteOfHour,
386                int secondOfMinute) {
387            this(hourOfDay, minuteOfHour, secondOfMinute, 0, ISOChronology.getInstanceUTC());
388        }
389    
390        /**
391         * Constructs an instance set to the specified time
392         * using <code>ISOChronology</code>.
393         *
394         * @param hourOfDay  the hour of the day
395         * @param minuteOfHour  the minute of the hour
396         * @param secondOfMinute  the second of the minute
397         * @param millisOfSecond  the millisecond of the second
398         */
399        public LocalTime(
400                int hourOfDay,
401                int minuteOfHour,
402                int secondOfMinute,
403                int millisOfSecond) {
404            this(hourOfDay, minuteOfHour, secondOfMinute,
405                    millisOfSecond, ISOChronology.getInstanceUTC());
406        }
407    
408        /**
409         * Constructs an instance set to the specified time
410         * using the specified chronology, whose zone is ignored.
411         * <p>
412         * If the chronology is null, <code>ISOChronology</code> is used.
413         *
414         * @param hourOfDay  the hour of the day
415         * @param minuteOfHour  the minute of the hour
416         * @param secondOfMinute  the second of the minute
417         * @param millisOfSecond  the millisecond of the second
418         * @param chronology  the chronology, null means ISOChronology in default zone
419         */
420        public LocalTime(
421                int hourOfDay,
422                int minuteOfHour,
423                int secondOfMinute,
424                int millisOfSecond,
425                Chronology chronology) {
426            super();
427            chronology = DateTimeUtils.getChronology(chronology).withUTC();
428            long instant = chronology.getDateTimeMillis(
429                0L, hourOfDay, minuteOfHour, secondOfMinute, millisOfSecond);
430            iChronology = chronology;
431            iLocalMillis = instant;
432        }
433    
434        //-----------------------------------------------------------------------
435        /**
436         * Gets the number of fields in this partial, which is four.
437         * The supported fields are HourOfDay, MinuteOfHour, SecondOfMinute
438         * and MillisOfSecond.
439         *
440         * @return the field count, four
441         */
442        public int size() {
443            return 4;
444        }
445    
446        /**
447         * Gets the field for a specific index in the chronology specified.
448         * <p>
449         * This method must not use any instance variables.
450         *
451         * @param index  the index to retrieve
452         * @param chrono  the chronology to use
453         * @return the field
454         */
455        protected DateTimeField getField(int index, Chronology chrono) {
456            switch (index) {
457                case HOUR_OF_DAY:
458                    return chrono.hourOfDay();
459                case MINUTE_OF_HOUR:
460                    return chrono.minuteOfHour();
461                case SECOND_OF_MINUTE:
462                    return chrono.secondOfMinute();
463                case MILLIS_OF_SECOND:
464                    return chrono.millisOfSecond();
465                default:
466                    throw new IndexOutOfBoundsException("Invalid index: " + index);
467            }
468        }
469    
470        /**
471         * Gets the value of the field at the specifed index.
472         * <p>
473         * This method is required to support the <code>ReadablePartial</code>
474         * interface. The supported fields are HourOfDay, MinuteOfHour,
475         * SecondOfMinute and MillisOfSecond.
476         *
477         * @param index  the index, zero to three
478         * @return the value
479         * @throws IndexOutOfBoundsException if the index is invalid
480         */
481        public int getValue(int index) {
482            switch (index) {
483                case HOUR_OF_DAY:
484                    return getChronology().hourOfDay().get(getLocalMillis());
485                case MINUTE_OF_HOUR:
486                    return getChronology().minuteOfHour().get(getLocalMillis());
487                case SECOND_OF_MINUTE:
488                    return getChronology().secondOfMinute().get(getLocalMillis());
489                case MILLIS_OF_SECOND:
490                    return getChronology().millisOfSecond().get(getLocalMillis());
491                default:
492                    throw new IndexOutOfBoundsException("Invalid index: " + index);
493            }
494        }
495    
496        //-----------------------------------------------------------------------
497        /**
498         * Get the value of one of the fields of time.
499         * <p>
500         * This method gets the value of the specified field.
501         * For example:
502         * <pre>
503         * DateTime dt = new DateTime();
504         * int hourOfDay = dt.get(DateTimeFieldType.hourOfDay());
505         * </pre>
506         *
507         * @param fieldType  a field type, usually obtained from DateTimeFieldType, not null
508         * @return the value of that field
509         * @throws IllegalArgumentException if the field type is null
510         */
511        public int get(DateTimeFieldType fieldType) {
512            if (fieldType == null) {
513                throw new IllegalArgumentException("The DateTimeFieldType must not be null");
514            }
515            if (isSupported(fieldType) == false) {
516                throw new IllegalArgumentException("Field '" + fieldType + "' is not supported");
517            }
518            return fieldType.getField(getChronology()).get(getLocalMillis());
519        }
520    
521        /**
522         * Checks if the field type specified is supported by this
523         * local time and chronology.
524         * This can be used to avoid exceptions in {@link #get(DateTimeFieldType)}.
525         *
526         * @param type  a field type, usually obtained from DateTimeFieldType
527         * @return true if the field type is supported
528         */
529        public boolean isSupported(DateTimeFieldType type) {
530            if (type == null) {
531                return false;
532            }
533            if (isSupported(type.getDurationType()) == false) {
534                return false;
535            }
536            DurationFieldType range = type.getRangeDurationType();
537            return (isSupported(range) || range == DurationFieldType.days());
538        }
539    
540        /**
541         * Checks if the duration type specified is supported by this
542         * local time and chronology.
543         *
544         * @param type  a duration type, usually obtained from DurationFieldType
545         * @return true if the field type is supported
546         */
547        public boolean isSupported(DurationFieldType type) {
548            if (type == null) {
549                return false;
550            }
551            DurationField field = type.getField(getChronology());
552            if (TIME_DURATION_TYPES.contains(type) ||
553                field.getUnitMillis() < getChronology().days().getUnitMillis()) {
554                return field.isSupported();
555            }
556            return false;
557        }
558    
559        //-----------------------------------------------------------------------
560        /**
561         * Gets the local milliseconds from the Java epoch
562         * of 1970-01-01T00:00:00 (not fixed to any specific time zone).
563         * 
564         * @return the number of milliseconds since 1970-01-01T00:00:00
565         * @since 1.5 (previously private)
566         */
567        protected long getLocalMillis() {
568            return iLocalMillis;
569        }
570    
571        /**
572         * Gets the chronology of the time.
573         * 
574         * @return the Chronology that the time is using
575         */
576        public Chronology getChronology() {
577            return iChronology;
578        }
579    
580        //-----------------------------------------------------------------------
581        /**
582         * Compares this ReadablePartial with another returning true if the chronology,
583         * field types and values are equal.
584         *
585         * @param partial  an object to check against
586         * @return true if fields and values are equal
587         */
588        public boolean equals(Object partial) {
589            // override to perform faster
590            if (this == partial) {
591                return true;
592            }
593            if (partial instanceof LocalTime) {
594                LocalTime other = (LocalTime) partial;
595                if (iChronology.equals(other.iChronology)) {
596                    return iLocalMillis == other.iLocalMillis;
597                }
598            }
599            return super.equals(partial);
600        }
601    
602        /**
603         * Compares this partial with another returning an integer
604         * indicating the order.
605         * <p>
606         * The fields are compared in order, from largest to smallest.
607         * The first field that is non-equal is used to determine the result.
608         * <p>
609         * The specified object must be a partial instance whose field types
610         * match those of this partial.
611         * <p>
612         * NOTE: This implementation violates the Comparable contract.
613         * This method will accept any instance of ReadablePartial as input.
614         * However, it is possible that some implementations of ReadablePartial
615         * exist that do not extend AbstractPartial, and thus will throw a
616         * ClassCastException if compared in the opposite direction.
617         * The cause of this problem is that ReadablePartial doesn't define
618         * the compareTo() method, however we can't change that until v2.0.
619         *
620         * @param partial  an object to check against
621         * @return negative if this is less, zero if equal, positive if greater
622         * @throws ClassCastException if the partial is the wrong class
623         *  or if it has field types that don't match
624         * @throws NullPointerException if the partial is null
625         */
626        public int compareTo(Object partial) {
627            // override to perform faster
628            if (this == partial) {
629                return 0;
630            }
631            if (partial instanceof LocalTime) {
632                LocalTime other = (LocalTime) partial;
633                if (iChronology.equals(other.iChronology)) {
634                    return (iLocalMillis < other.iLocalMillis ? -1 :
635                                (iLocalMillis == other.iLocalMillis ? 0 : 1));
636    
637                }
638            }
639            return super.compareTo(partial);
640        }
641    
642        //-----------------------------------------------------------------------
643        /**
644         * Returns a copy of this time with different local millis.
645         * <p>
646         * The returned object will be a new instance of the same type.
647         * Only the millis will change, the chronology is kept.
648         * The returned object will be either be a new instance or <code>this</code>.
649         *
650         * @param newMillis  the new millis, from 1970-01-01T00:00:00
651         * @return a copy of this time with different millis
652         */
653        LocalTime withLocalMillis(long newMillis) {
654            return (newMillis == getLocalMillis() ? this : new LocalTime(newMillis, getChronology()));
655        }
656    
657        //-----------------------------------------------------------------------
658        /**
659         * Returns a copy of this time with the partial set of fields replacing
660         * those from this instance.
661         * <p>
662         * For example, if the partial contains an hour and minute then those two
663         * fields will be changed in the returned instance.
664         * Unsupported fields are ignored.
665         * If the partial is null, then <code>this</code> is returned.
666         *
667         * @param partial  the partial set of fields to apply to this time, null ignored
668         * @return a copy of this time with a different set of fields
669         * @throws IllegalArgumentException if any value is invalid
670         */
671        public LocalTime withFields(ReadablePartial partial) {
672            if (partial == null) {
673                return this;
674            }
675            return withLocalMillis(getChronology().set(partial, getLocalMillis()));
676        }
677    
678        /**
679         * Returns a copy of this time with the specified field set
680         * to a new value.
681         * <p>
682         * For example, if the field type is <code>hourOfDay</code> then the hour of day
683         * field would be changed in the returned instance.
684         * If the field type is null, then <code>this</code> is returned.
685         * <p>
686         * These lines are equivalent:
687         * <pre>
688         * LocalTime updated = dt.withHourOfDay(6);
689         * LocalTime updated = dt.withField(DateTimeFieldType.hourOfDay(), 6);
690         * </pre>
691         *
692         * @param fieldType  the field type to set, not null
693         * @param value  the value to set
694         * @return a copy of this time with the field set
695         * @throws IllegalArgumentException if the value is null or invalid
696         */
697        public LocalTime withField(DateTimeFieldType fieldType, int value) {
698            if (fieldType == null) {
699                throw new IllegalArgumentException("Field must not be null");
700            }
701            if (isSupported(fieldType) == false) {
702                throw new IllegalArgumentException("Field '" + fieldType + "' is not supported");
703            }
704            long instant = fieldType.getField(getChronology()).set(getLocalMillis(), value);
705            return withLocalMillis(instant);
706        }
707    
708        /**
709         * Returns a copy of this time with the value of the specified
710         * field increased.
711         * <p>
712         * If the addition is zero or the field is null, then <code>this</code>
713         * is returned.
714         * <p>
715         * If the addition causes the maximum value of the field to be exceeded,
716         * then the value will wrap. Thus 23:59 plus two minutes yields 00:01.
717         * <p>
718         * These lines are equivalent:
719         * <pre>
720         * LocalTime added = dt.plusHours(6);
721         * LocalTime added = dt.withFieldAdded(DurationFieldType.hours(), 6);
722         * </pre>
723         *
724         * @param fieldType  the field type to add to, not null
725         * @param amount  the amount to add
726         * @return a copy of this time with the field updated
727         * @throws IllegalArgumentException if the value is null or invalid
728         * @throws ArithmeticException if the result exceeds the internal capacity
729         */
730        public LocalTime withFieldAdded(DurationFieldType fieldType, int amount) {
731            if (fieldType == null) {
732                throw new IllegalArgumentException("Field must not be null");
733            }
734            if (isSupported(fieldType) == false) {
735                throw new IllegalArgumentException("Field '" + fieldType + "' is not supported");
736            }
737            if (amount == 0) {
738                return this;
739            }
740            long instant = fieldType.getField(getChronology()).add(getLocalMillis(), amount);
741            return withLocalMillis(instant);
742        }
743    
744        //-----------------------------------------------------------------------
745        /**
746         * Returns a copy of this time with the specified period added.
747         * <p>
748         * If the addition is zero, then <code>this</code> is returned.
749         * <p>
750         * This method is typically used to add multiple copies of complex
751         * period instances. Adding one field is best achieved using methods
752         * like {@link #withFieldAdded(DurationFieldType, int)}
753         * or {@link #plusHours(int)}.
754         *
755         * @param period  the period to add to this one, null means zero
756         * @param scalar  the amount of times to add, such as -1 to subtract once
757         * @return a copy of this time with the period added
758         * @throws ArithmeticException if the result exceeds the internal capacity
759         */
760        public LocalTime withPeriodAdded(ReadablePeriod period, int scalar) {
761            if (period == null || scalar == 0) {
762                return this;
763            }
764            long instant = getChronology().add(period, getLocalMillis(), scalar);
765            return withLocalMillis(instant);
766        }
767    
768        //-----------------------------------------------------------------------
769        /**
770         * Returns a copy of this time with the specified period added.
771         * <p>
772         * If the amount is zero or null, then <code>this</code> is returned.
773         * <p>
774         * This method is typically used to add complex period instances.
775         * Adding one field is best achieved using methods
776         * like {@link #plusHours(int)}.
777         * 
778         * @param period  the period to add to this one, null means zero
779         * @return a copy of this time with the period added
780         * @throws ArithmeticException if the result exceeds the internal capacity
781         */
782        public LocalTime plus(ReadablePeriod period) {
783            return withPeriodAdded(period, 1);
784        }
785    
786        //-----------------------------------------------------------------------
787        /**
788         * Returns a copy of this time plus the specified number of hours.
789         * <p>
790         * This LocalTime instance is immutable and unaffected by this method call.
791         * <p>
792         * The following three lines are identical in effect:
793         * <pre>
794         * LocalTime added = dt.plusHours(6);
795         * LocalTime added = dt.plus(Period.hours(6));
796         * LocalTime added = dt.withFieldAdded(DurationFieldType.hours(), 6);
797         * </pre>
798         *
799         * @param hours  the amount of hours to add, may be negative
800         * @return the new LocalTime plus the increased hours
801         */
802        public LocalTime plusHours(int hours) {
803            if (hours == 0) {
804                return this;
805            }
806            long instant = getChronology().hours().add(getLocalMillis(), hours);
807            return withLocalMillis(instant);
808        }
809    
810        /**
811         * Returns a copy of this time plus the specified number of minutes.
812         * <p>
813         * This LocalTime instance is immutable and unaffected by this method call.
814         * <p>
815         * The following three lines are identical in effect:
816         * <pre>
817         * LocalTime added = dt.plusMinutes(6);
818         * LocalTime added = dt.plus(Period.minutes(6));
819         * LocalTime added = dt.withFieldAdded(DurationFieldType.minutes(), 6);
820         * </pre>
821         *
822         * @param minutes  the amount of minutes to add, may be negative
823         * @return the new LocalTime plus the increased minutes
824         */
825        public LocalTime plusMinutes(int minutes) {
826            if (minutes == 0) {
827                return this;
828            }
829            long instant = getChronology().minutes().add(getLocalMillis(), minutes);
830            return withLocalMillis(instant);
831        }
832    
833        /**
834         * Returns a copy of this time plus the specified number of seconds.
835         * <p>
836         * This LocalTime instance is immutable and unaffected by this method call.
837         * <p>
838         * The following three lines are identical in effect:
839         * <pre>
840         * LocalTime added = dt.plusSeconds(6);
841         * LocalTime added = dt.plus(Period.seconds(6));
842         * LocalTime added = dt.withFieldAdded(DurationFieldType.seconds(), 6);
843         * </pre>
844         *
845         * @param seconds  the amount of seconds to add, may be negative
846         * @return the new LocalTime plus the increased seconds
847         */
848        public LocalTime plusSeconds(int seconds) {
849            if (seconds == 0) {
850                return this;
851            }
852            long instant = getChronology().seconds().add(getLocalMillis(), seconds);
853            return withLocalMillis(instant);
854        }
855    
856        /**
857         * Returns a copy of this time plus the specified number of millis.
858         * <p>
859         * This LocalTime instance is immutable and unaffected by this method call.
860         * <p>
861         * The following three lines are identical in effect:
862         * <pre>
863         * LocalTime added = dt.plusMillis(6);
864         * LocalTime added = dt.plus(Period.millis(6));
865         * LocalTime added = dt.withFieldAdded(DurationFieldType.millis(), 6);
866         * </pre>
867         *
868         * @param millis  the amount of millis to add, may be negative
869         * @return the new LocalTime plus the increased millis
870         */
871        public LocalTime plusMillis(int millis) {
872            if (millis == 0) {
873                return this;
874            }
875            long instant = getChronology().millis().add(getLocalMillis(), millis);
876            return withLocalMillis(instant);
877        }
878    
879        //-----------------------------------------------------------------------
880        /**
881         * Returns a copy of this time with the specified period taken away.
882         * <p>
883         * If the amount is zero or null, then <code>this</code> is returned.
884         * <p>
885         * This method is typically used to subtract complex period instances.
886         * Subtracting one field is best achieved using methods
887         * like {@link #minusHours(int)}.
888         * 
889         * @param period  the period to reduce this instant by
890         * @return a copy of this time with the period taken away
891         * @throws ArithmeticException if the result exceeds the internal capacity
892         */
893        public LocalTime minus(ReadablePeriod period) {
894            return withPeriodAdded(period, -1);
895        }
896    
897        //-----------------------------------------------------------------------
898        /**
899         * Returns a copy of this time minus the specified number of hours.
900         * <p>
901         * This LocalTime instance is immutable and unaffected by this method call.
902         * <p>
903         * The following three lines are identical in effect:
904         * <pre>
905         * LocalTime subtracted = dt.minusHours(6);
906         * LocalTime subtracted = dt.minus(Period.hours(6));
907         * LocalTime subtracted = dt.withFieldAdded(DurationFieldType.hours(), -6);
908         * </pre>
909         *
910         * @param hours  the amount of hours to subtract, may be negative
911         * @return the new LocalTime minus the increased hours
912         */
913        public LocalTime minusHours(int hours) {
914            if (hours == 0) {
915                return this;
916            }
917            long instant = getChronology().hours().subtract(getLocalMillis(), hours);
918            return withLocalMillis(instant);
919        }
920    
921        /**
922         * Returns a copy of this time minus the specified number of minutes.
923         * <p>
924         * This LocalTime instance is immutable and unaffected by this method call.
925         * <p>
926         * The following three lines are identical in effect:
927         * <pre>
928         * LocalTime subtracted = dt.minusMinutes(6);
929         * LocalTime subtracted = dt.minus(Period.minutes(6));
930         * LocalTime subtracted = dt.withFieldAdded(DurationFieldType.minutes(), -6);
931         * </pre>
932         *
933         * @param minutes  the amount of minutes to subtract, may be negative
934         * @return the new LocalTime minus the increased minutes
935         */
936        public LocalTime minusMinutes(int minutes) {
937            if (minutes == 0) {
938                return this;
939            }
940            long instant = getChronology().minutes().subtract(getLocalMillis(), minutes);
941            return withLocalMillis(instant);
942        }
943    
944        /**
945         * Returns a copy of this time minus the specified number of seconds.
946         * <p>
947         * This LocalTime instance is immutable and unaffected by this method call.
948         * <p>
949         * The following three lines are identical in effect:
950         * <pre>
951         * LocalTime subtracted = dt.minusSeconds(6);
952         * LocalTime subtracted = dt.minus(Period.seconds(6));
953         * LocalTime subtracted = dt.withFieldAdded(DurationFieldType.seconds(), -6);
954         * </pre>
955         *
956         * @param seconds  the amount of seconds to subtract, may be negative
957         * @return the new LocalTime minus the increased seconds
958         */
959        public LocalTime minusSeconds(int seconds) {
960            if (seconds == 0) {
961                return this;
962            }
963            long instant = getChronology().seconds().subtract(getLocalMillis(), seconds);
964            return withLocalMillis(instant);
965        }
966    
967        /**
968         * Returns a copy of this time minus the specified number of millis.
969         * <p>
970         * This LocalTime instance is immutable and unaffected by this method call.
971         * <p>
972         * The following three lines are identical in effect:
973         * <pre>
974         * LocalTime subtracted = dt.minusMillis(6);
975         * LocalTime subtracted = dt.minus(Period.millis(6));
976         * LocalTime subtracted = dt.withFieldAdded(DurationFieldType.millis(), -6);
977         * </pre>
978         *
979         * @param millis  the amount of millis to subtract, may be negative
980         * @return the new LocalTime minus the increased millis
981         */
982        public LocalTime minusMillis(int millis) {
983            if (millis == 0) {
984                return this;
985            }
986            long instant = getChronology().millis().subtract(getLocalMillis(), millis);
987            return withLocalMillis(instant);
988        }
989    
990        //-----------------------------------------------------------------------
991        /**
992         * Gets the property object for the specified type, which contains
993         * many useful methods.
994         *
995         * @param fieldType  the field type to get the chronology for
996         * @return the property object
997         * @throws IllegalArgumentException if the field is null or unsupported
998         */
999        public Property property(DateTimeFieldType fieldType) {
1000            if (fieldType == null) {
1001                throw new IllegalArgumentException("The DateTimeFieldType must not be null");
1002            }
1003            if (isSupported(fieldType) == false) {
1004                throw new IllegalArgumentException("Field '" + fieldType + "' is not supported");
1005            }
1006            return new Property(this, fieldType.getField(getChronology()));
1007        }
1008    
1009        //-----------------------------------------------------------------------
1010        /**
1011         * Get the hour of day field value.
1012         *
1013         * @return the hour of day
1014         */
1015        public int getHourOfDay() {
1016            return getChronology().hourOfDay().get(getLocalMillis());
1017        }
1018    
1019        /**
1020         * Get the minute of hour field value.
1021         *
1022         * @return the minute of hour
1023         */
1024        public int getMinuteOfHour() {
1025            return getChronology().minuteOfHour().get(getLocalMillis());
1026        }
1027    
1028        /**
1029         * Get the second of minute field value.
1030         *
1031         * @return the second of minute
1032         */
1033        public int getSecondOfMinute() {
1034            return getChronology().secondOfMinute().get(getLocalMillis());
1035        }
1036    
1037        /**
1038         * Get the millis of second field value.
1039         *
1040         * @return the millis of second
1041         */
1042        public int getMillisOfSecond() {
1043            return getChronology().millisOfSecond().get(getLocalMillis());
1044        }
1045    
1046        /**
1047         * Get the millis of day field value.
1048         *
1049         * @return the millis of day
1050         */
1051        public int getMillisOfDay() {
1052            return getChronology().millisOfDay().get(getLocalMillis());
1053        }
1054    
1055        //-----------------------------------------------------------------------
1056        /**
1057         * Returns a copy of this time with the hour of day field updated.
1058         * <p>
1059         * LocalTime is immutable, so there are no set methods.
1060         * Instead, this method returns a new instance with the value of
1061         * hour of day changed.
1062         *
1063         * @param hour  the hour of day to set
1064         * @return a copy of this object with the field set
1065         * @throws IllegalArgumentException if the value is invalid
1066         */
1067        public LocalTime withHourOfDay(int hour) {
1068            return withLocalMillis(getChronology().hourOfDay().set(getLocalMillis(), hour));
1069        }
1070    
1071        /**
1072         * Returns a copy of this time with the minute of hour field updated.
1073         * <p>
1074         * LocalTime is immutable, so there are no set methods.
1075         * Instead, this method returns a new instance with the value of
1076         * minute of hour changed.
1077         *
1078         * @param minute  the minute of hour to set
1079         * @return a copy of this object with the field set
1080         * @throws IllegalArgumentException if the value is invalid
1081         */
1082        public LocalTime withMinuteOfHour(int minute) {
1083            return withLocalMillis(getChronology().minuteOfHour().set(getLocalMillis(), minute));
1084        }
1085    
1086        /**
1087         * Returns a copy of this time with the second of minute field updated.
1088         * <p>
1089         * LocalTime is immutable, so there are no set methods.
1090         * Instead, this method returns a new instance with the value of
1091         * second of minute changed.
1092         *
1093         * @param second  the second of minute to set
1094         * @return a copy of this object with the field set
1095         * @throws IllegalArgumentException if the value is invalid
1096         */
1097        public LocalTime withSecondOfMinute(int second) {
1098            return withLocalMillis(getChronology().secondOfMinute().set(getLocalMillis(), second));
1099        }
1100    
1101        /**
1102         * Returns a copy of this time with the millis of second field updated.
1103         * <p>
1104         * LocalTime is immutable, so there are no set methods.
1105         * Instead, this method returns a new instance with the value of
1106         * millis of second changed.
1107         *
1108         * @param millis  the millis of second to set
1109         * @return a copy of this object with the field set
1110         * @throws IllegalArgumentException if the value is invalid
1111         */
1112        public LocalTime withMillisOfSecond(int millis) {
1113            return withLocalMillis(getChronology().millisOfSecond().set(getLocalMillis(), millis));
1114        }
1115    
1116        /**
1117         * Returns a copy of this time with the millis of day field updated.
1118         * <p>
1119         * LocalTime is immutable, so there are no set methods.
1120         * Instead, this method returns a new instance with the value of
1121         * millis of day changed.
1122         *
1123         * @param millis  the millis of day to set
1124         * @return a copy of this object with the field set
1125         * @throws IllegalArgumentException if the value is invalid
1126         */
1127        public LocalTime withMillisOfDay(int millis) {
1128            return withLocalMillis(getChronology().millisOfDay().set(getLocalMillis(), millis));
1129        }
1130    
1131        //-----------------------------------------------------------------------
1132        /**
1133         * Get the hour of day field property which provides access to advanced functionality.
1134         * 
1135         * @return the hour of day property
1136         */
1137        public Property hourOfDay() {
1138            return new Property(this, getChronology().hourOfDay());
1139        }
1140    
1141        /**
1142         * Get the minute of hour field property which provides access to advanced functionality.
1143         * 
1144         * @return the minute of hour property
1145         */
1146        public Property minuteOfHour() {
1147            return new Property(this, getChronology().minuteOfHour());
1148        }
1149    
1150        /**
1151         * Get the second of minute field property which provides access to advanced functionality.
1152         * 
1153         * @return the second of minute property
1154         */
1155        public Property secondOfMinute() {
1156            return new Property(this, getChronology().secondOfMinute());
1157        }
1158    
1159        /**
1160         * Get the millis of second property which provides access to advanced functionality.
1161         * 
1162         * @return the millis of second property
1163         */
1164        public Property millisOfSecond() {
1165            return new Property(this, getChronology().millisOfSecond());
1166        }
1167    
1168        /**
1169         * Get the millis of day property which provides access to advanced functionality.
1170         * 
1171         * @return the millis of day property
1172         */
1173        public Property millisOfDay() {
1174            return new Property(this, getChronology().millisOfDay());
1175        }
1176    
1177        //-----------------------------------------------------------------------
1178        /**
1179         * Converts this LocalTime to a full datetime using the default time zone
1180         * setting the time fields from this instance and the date fields from
1181         * the current date.
1182         *
1183         * @return this time as a datetime using todays date
1184         */
1185        public DateTime toDateTimeToday() {
1186            return toDateTimeToday(null);
1187        }
1188    
1189        /**
1190         * Converts this LocalTime to a full datetime using the specified time zone
1191         * setting the time fields from this instance and the date fields from
1192         * the current time.
1193         * <p>
1194         * This method uses the chronology from this instance plus the time zone
1195         * specified.
1196         *
1197         * @param zone  the zone to use, null means default
1198         * @return this time as a datetime using todays date
1199         */
1200        public DateTime toDateTimeToday(DateTimeZone zone) {
1201            Chronology chrono = getChronology().withZone(zone);
1202            long instantMillis = DateTimeUtils.currentTimeMillis();
1203            long resolved = chrono.set(this, instantMillis);
1204            return new DateTime(resolved, chrono);
1205        }
1206    
1207        //-----------------------------------------------------------------------
1208        /**
1209         * Output the time in ISO8601 format (HH:mm:ss.SSSZZ).
1210         * 
1211         * @return ISO8601 time formatted string.
1212         */
1213        public String toString() {
1214            return ISODateTimeFormat.time().print(this);
1215        }
1216    
1217        /**
1218         * Output the time using the specified format pattern.
1219         *
1220         * @param pattern  the pattern specification, null means use <code>toString</code>
1221         * @see org.joda.time.format.DateTimeFormat
1222         */
1223        public String toString(String pattern) {
1224            if (pattern == null) {
1225                return toString();
1226            }
1227            return DateTimeFormat.forPattern(pattern).print(this);
1228        }
1229    
1230        /**
1231         * Output the time using the specified format pattern.
1232         *
1233         * @param pattern  the pattern specification, null means use <code>toString</code>
1234         * @param locale  Locale to use, null means default
1235         * @see org.joda.time.format.DateTimeFormat
1236         */
1237        public String toString(String pattern, Locale locale) throws IllegalArgumentException {
1238            if (pattern == null) {
1239                return toString();
1240            }
1241            return DateTimeFormat.forPattern(pattern).withLocale(locale).print(this);
1242        }
1243    
1244        //-----------------------------------------------------------------------
1245        /**
1246         * LocalTime.Property binds a LocalTime to a DateTimeField allowing
1247         * powerful datetime functionality to be easily accessed.
1248         * <p>
1249         * The simplest use of this class is as an alternative get method, here used to
1250         * get the minute '30'.
1251         * <pre>
1252         * LocalTime dt = new LocalTime(12, 30);
1253         * int year = dt.minuteOfHour().get();
1254         * </pre>
1255         * <p>
1256         * Methods are also provided that allow time modification. These return
1257         * new instances of LocalTime - they do not modify the original. The example
1258         * below yields two independent immutable date objects 2 hours apart.
1259         * <pre>
1260         * LocalTime dt1230 = new LocalTime(12, 30);
1261         * LocalTime dt1430 = dt1230.hourOfDay().setCopy(14);
1262         * </pre>
1263         * <p>
1264         * LocalTime.Property itself is thread-safe and immutable, as well as the
1265         * LocalTime being operated on.
1266         *
1267         * @author Stephen Colebourne
1268         * @author Brian S O'Neill
1269         * @since 1.3
1270         */
1271        public static final class Property extends AbstractReadableInstantFieldProperty {
1272            
1273            /** Serialization version */
1274            private static final long serialVersionUID = -325842547277223L;
1275            
1276            /** The instant this property is working against */
1277            private transient LocalTime iInstant;
1278            /** The field this property is working against */
1279            private transient DateTimeField iField;
1280            
1281            /**
1282             * Constructor.
1283             * 
1284             * @param instant  the instant to set
1285             * @param field  the field to use
1286             */
1287            Property(LocalTime instant, DateTimeField field) {
1288                super();
1289                iInstant = instant;
1290                iField = field;
1291            }
1292            
1293            /**
1294             * Writes the property in a safe serialization format.
1295             */
1296            private void writeObject(ObjectOutputStream oos) throws IOException {
1297                oos.writeObject(iInstant);
1298                oos.writeObject(iField.getType());
1299            }
1300            
1301            /**
1302             * Reads the property from a safe serialization format.
1303             */
1304            private void readObject(ObjectInputStream oos) throws IOException, ClassNotFoundException {
1305                iInstant = (LocalTime) oos.readObject();
1306                DateTimeFieldType type = (DateTimeFieldType) oos.readObject();
1307                iField = type.getField(iInstant.getChronology());
1308            }
1309            
1310            //-----------------------------------------------------------------------
1311            /**
1312             * Gets the field being used.
1313             * 
1314             * @return the field
1315             */
1316            public DateTimeField getField() {
1317                return iField;
1318            }
1319            
1320            /**
1321             * Gets the milliseconds of the time that this property is linked to.
1322             * 
1323             * @return the milliseconds
1324             */
1325            protected long getMillis() {
1326                return iInstant.getLocalMillis();
1327            }
1328            
1329            /**
1330             * Gets the chronology of the datetime that this property is linked to.
1331             * 
1332             * @return the chronology
1333             * @since 1.4
1334             */
1335            protected Chronology getChronology() {
1336                return iInstant.getChronology();
1337            }
1338            
1339            /**
1340             * Gets the LocalTime object linked to this property.
1341             * 
1342             * @return the linked LocalTime
1343             */
1344            public LocalTime getLocalTime() {
1345                return iInstant;
1346            }
1347            
1348            //-----------------------------------------------------------------------
1349            /**
1350             * Adds to this field in a copy of this LocalTime.
1351             * <p>
1352             * The LocalTime attached to this property is unchanged by this call.
1353             *
1354             * @param value  the value to add to the field in the copy
1355             * @return a copy of the LocalTime with the field value changed
1356             */
1357            public LocalTime addCopy(int value) {
1358                return iInstant.withLocalMillis(iField.add(iInstant.getLocalMillis(), value));
1359            }
1360            
1361            /**
1362             * Adds to this field in a copy of this LocalTime.
1363             * If the addition exceeds the maximum value (eg. 23:59) it will
1364             * wrap to the minimum value (eg. 00:00).
1365             * <p>
1366             * The LocalTime attached to this property is unchanged by this call.
1367             *
1368             * @param value  the value to add to the field in the copy
1369             * @return a copy of the LocalTime with the field value changed
1370             */
1371            public LocalTime addCopy(long value) {
1372                return iInstant.withLocalMillis(iField.add(iInstant.getLocalMillis(), value));
1373            }
1374            
1375            /**
1376             * Adds to this field in a copy of this LocalTime.
1377             * If the addition exceeds the maximum value (eg. 23:59) then
1378             * an exception will be thrown.
1379             * Contrast this behaviour to {@link #addCopy(int)}.
1380             * <p>
1381             * The LocalTime attached to this property is unchanged by this call.
1382             *
1383             * @param value  the value to add to the field in the copy
1384             * @return a copy of the LocalTime with the field value changed
1385             * @throws IllegalArgumentException if the result is invalid
1386             */
1387            public LocalTime addNoWrapToCopy(int value) {
1388                long millis = iField.add(iInstant.getLocalMillis(), value);
1389                long rounded = iInstant.getChronology().millisOfDay().get(millis);
1390                if (rounded != millis) {
1391                    throw new IllegalArgumentException("The addition exceeded the boundaries of LocalTime");
1392                }
1393                return iInstant.withLocalMillis(millis);
1394            }
1395            
1396            /**
1397             * Adds to this field, possibly wrapped, in a copy of this LocalTime.
1398             * A field wrapped operation only changes this field.
1399             * Thus 10:59 plusWrapField one minute goes to 10:00.
1400             * <p>
1401             * The LocalTime attached to this property is unchanged by this call.
1402             *
1403             * @param value  the value to add to the field in the copy
1404             * @return a copy of the LocalTime with the field value changed
1405             * @throws IllegalArgumentException if the value isn't valid
1406             */
1407            public LocalTime addWrapFieldToCopy(int value) {
1408                return iInstant.withLocalMillis(iField.addWrapField(iInstant.getLocalMillis(), value));
1409            }
1410            
1411            //-----------------------------------------------------------------------
1412            /**
1413             * Sets this field in a copy of the LocalTime.
1414             * <p>
1415             * The LocalTime attached to this property is unchanged by this call.
1416             *
1417             * @param value  the value to set the field in the copy to
1418             * @return a copy of the LocalTime with the field value changed
1419             * @throws IllegalArgumentException if the value isn't valid
1420             */
1421            public LocalTime setCopy(int value) {
1422                return iInstant.withLocalMillis(iField.set(iInstant.getLocalMillis(), value));
1423            }
1424            
1425            /**
1426             * Sets this field in a copy of the LocalTime to a parsed text value.
1427             * <p>
1428             * The LocalTime attached to this property is unchanged by this call.
1429             *
1430             * @param text  the text value to set
1431             * @param locale  optional locale to use for selecting a text symbol
1432             * @return a copy of the LocalTime with the field value changed
1433             * @throws IllegalArgumentException if the text value isn't valid
1434             */
1435            public LocalTime setCopy(String text, Locale locale) {
1436                return iInstant.withLocalMillis(iField.set(iInstant.getLocalMillis(), text, locale));
1437            }
1438            
1439            /**
1440             * Sets this field in a copy of the LocalTime to a parsed text value.
1441             * <p>
1442             * The LocalTime attached to this property is unchanged by this call.
1443             *
1444             * @param text  the text value to set
1445             * @return a copy of the LocalTime with the field value changed
1446             * @throws IllegalArgumentException if the text value isn't valid
1447             */
1448            public LocalTime setCopy(String text) {
1449                return setCopy(text, null);
1450            }
1451            
1452            //-----------------------------------------------------------------------
1453            /**
1454             * Returns a new LocalTime with this field set to the maximum value
1455             * for this field.
1456             * <p>
1457             * The LocalTime attached to this property is unchanged by this call.
1458             *
1459             * @return a copy of the LocalTime with this field set to its maximum
1460             */
1461            public LocalTime withMaximumValue() {
1462                return setCopy(getMaximumValue());
1463            }
1464            
1465            /**
1466             * Returns a new LocalTime with this field set to the minimum value
1467             * for this field.
1468             * <p>
1469             * The LocalTime attached to this property is unchanged by this call.
1470             *
1471             * @return a copy of the LocalTime with this field set to its minimum
1472             */
1473            public LocalTime withMinimumValue() {
1474                return setCopy(getMinimumValue());
1475            }
1476            
1477            //-----------------------------------------------------------------------
1478            /**
1479             * Rounds to the lowest whole unit of this field on a copy of this
1480             * LocalTime.
1481             * <p>
1482             * For example, rounding floor on the hourOfDay field of a LocalTime
1483             * where the time is 10:30 would result in new LocalTime with the
1484             * time of 10:00.
1485             *
1486             * @return a copy of the LocalTime with the field value changed
1487             */
1488            public LocalTime roundFloorCopy() {
1489                return iInstant.withLocalMillis(iField.roundFloor(iInstant.getLocalMillis()));
1490            }
1491            
1492            /**
1493             * Rounds to the highest whole unit of this field on a copy of this
1494             * LocalTime.
1495             * <p>
1496             * For example, rounding floor on the hourOfDay field of a LocalTime
1497             * where the time is 10:30 would result in new LocalTime with the
1498             * time of 11:00.
1499             *
1500             * @return a copy of the LocalTime with the field value changed
1501             */
1502            public LocalTime roundCeilingCopy() {
1503                return iInstant.withLocalMillis(iField.roundCeiling(iInstant.getLocalMillis()));
1504            }
1505            
1506            /**
1507             * Rounds to the nearest whole unit of this field on a copy of this
1508             * LocalTime, favoring the floor if halfway.
1509             *
1510             * @return a copy of the LocalTime with the field value changed
1511             */
1512            public LocalTime roundHalfFloorCopy() {
1513                return iInstant.withLocalMillis(iField.roundHalfFloor(iInstant.getLocalMillis()));
1514            }
1515            
1516            /**
1517             * Rounds to the nearest whole unit of this field on a copy of this
1518             * LocalTime, favoring the ceiling if halfway.
1519             *
1520             * @return a copy of the LocalTime with the field value changed
1521             */
1522            public LocalTime roundHalfCeilingCopy() {
1523                return iInstant.withLocalMillis(iField.roundHalfCeiling(iInstant.getLocalMillis()));
1524            }
1525            
1526            /**
1527             * Rounds to the nearest whole unit of this field on a copy of this
1528             * LocalTime.  If halfway, the ceiling is favored over the floor
1529             * only if it makes this field's value even.
1530             *
1531             * @return a copy of the LocalTime with the field value changed
1532             */
1533            public LocalTime roundHalfEvenCopy() {
1534                return iInstant.withLocalMillis(iField.roundHalfEven(iInstant.getLocalMillis()));
1535            }
1536        }
1537    
1538    }